#include "Client.h"
#include "cameraDriver.h"
#include "RemoteHandle.h"
#include "WebMonitor.h"
#include <fstream>
#include <filesystem>
#include <unistd.h>

#define CHECK_EXCEPTION(a) \
try \
{ \
    a \
} \
catch(const std::exception& e) \
{ \
    remoteHandle->SendMessage(e.what()); \
    return; \
}

static cameraDriver* CameraDriver=nullptr;
static WebMonitor* webMonitor=nullptr;
static RemoteHandle* remoteHandle=nullptr;

enum class DeviceStatus:int32_t
{
    UnInit=0x1,
    Init=0x3,
    CameraShot=0x4,
    CmaeraSave=0x5,
    Error=0x0
} deviceStatus;

static std::list<cameraDriver::cameraDevice>::iterator cameraPtr;

//file data
std::string filePath; //最后一个字符为'/'
std::string ServerIP;
std::string ServerPort;
std::string DeviceName;

std::string fileName;

void ReadFileData()
{
    std::ifstream configFile;
    configFile.open("/etc/CameraCollege/config");
    if(!configFile.is_open())
    {
        OATPP_LOGE("Config","Can't open config file,the default config file path:/etc/CameraCollege/config");
        throw;
    }
    //这里DeviceName字段弃用了
    configFile>>filePath>>ServerIP>>ServerPort;
    //手动获取主机名
    char* hostname=new char[512];
    gethostname(hostname,512);
    DeviceName=std::string(hostname,512);
    delete [] hostname;
    if(!configFile.good())
    {
        OATPP_LOGE("Config","Can't Read Config File,please check file format");
        throw;
    }
    configFile.close();
    if(!std::filesystem::exists(filePath))
    {
        OATPP_LOGE("Config","Can't Open File Path");
        throw;
    }
    if(filePath.at(filePath.length()-1)!='/')
        filePath+='/';
}

Client::Client()
{
    deviceStatus=DeviceStatus::UnInit;
    CameraDriver=new cameraDriver();
    remoteHandle=new RemoteHandle(this);
    webMonitor=new WebMonitor(this,remoteHandle);
}

Client::~Client()
{
    delete webMonitor;
    delete remoteHandle;
    delete CameraDriver;
}

void Client::Run()
{
    ReadFileData();
    webMonitor->SetServerConfig(ServerIP,ServerPort,DeviceName);
    webMonitor->LoginServer();
}

void Client::sendErrorMessage(std::string msg)
{
    remoteHandle->SendMessage(fmt::format("错误:{}",msg));
}

void Client::sendPreviewImage(unsigned char* imageData,const int32_t imageHeight,const int32_t imageWidth,const pixelFormat imageFormat)
{
    remoteHandle->SetImage(imageData,imageHeight,imageWidth,imageFormat);
}

void Client::GetDeviceStatus()
{
    remoteHandle->SendDeviceStatus(static_cast<int32_t>(deviceStatus));
}

void Client::GetCameraParameter()
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CameraParament para={
            static_cast<int32_t>(cameraPtr->GetImageHeight()),
            static_cast<int32_t>(cameraPtr->GetImageWidth()),
            static_cast<int32_t>(cameraPtr->GetImageOffsetX()),
            static_cast<int32_t>(cameraPtr->GetImageOffsetY()),
            static_cast<int32_t>(cameraPtr->GetExposureTime()),
            static_cast<int>(cameraPtr->GetCollegeFrameRate()),
            cameraPtr->GetTriggerMode()? 0x1 : 0x0
        };
        remoteHandle->SendCameraPara(para);
    }
}

void Client::InitDevice()
{
    auto deviceList=CameraDriver->GetDeviceList();
    if(deviceList.size()==0)
    {
        deviceStatus=DeviceStatus::UnInit;
        return;
    }
    CHECK_EXCEPTION(cameraPtr=CameraDriver->OpenIndexCamera(1,this,0);cameraPtr->SetImageFPSControl(true);)
    deviceStatus=DeviceStatus::Init;
}

void Client::StartShot()
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->StartCollegeImage();)
        deviceStatus=DeviceStatus::CameraShot;
    }
}

void Client::StartSave()
{
    if(deviceStatus==DeviceStatus::CameraShot)
    {
        cameraPtr->SetImageSavePath(filePath.substr(0,filePath.length()-1));
        CHECK_EXCEPTION(fileName=cameraPtr->StartSaveImage();)
        deviceStatus=DeviceStatus::CmaeraSave;
    }
}

void Client::StopShot()
{
    if(deviceStatus==DeviceStatus::CameraShot)
    {
        CHECK_EXCEPTION(cameraPtr->StopCollegeImage();)
        deviceStatus=DeviceStatus::Init;
    }
}

void Client::StopSave()
{
    if(deviceStatus==DeviceStatus::CmaeraSave)
    {
        CHECK_EXCEPTION(cameraPtr->StopSaveImage();)
        deviceStatus=DeviceStatus::CameraShot;
    }
}

void Client::StartTrigger()
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetTriggerMode(true);)
    }
}

void Client::StopTrigger()
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetTriggerMode(false);)
    }
}

void Client::SetImageWidth(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetImageWidth(value);)
    }
}

void Client::SetImageHeight(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetImageHeight(value);)
    }
}

void Client::SetImageOffsetX(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetImageOffsetX(value);)
    }
}

void Client::SetImageOffsetY(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetImageOffsetY(value);)
    }
}

void Client::SetExposureTime(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetExposureTime(value);)
    }
}

void Client::SetFrameRate(int32_t value)
{
    if(deviceStatus==DeviceStatus::Init)
    {
        CHECK_EXCEPTION(cameraPtr->SetImageFPSRate(value);)
    }
}

void Client::FileTranslate()
{
    remoteHandle->FileTransfer(filePath+fileName);
}
